package model;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import databeans.MailingList;
import interfas.MailingListInterface;

public class MailingListDAO implements MailingListInterface {

	private BeanFactory<MailingList> factory;
	private int mlid = 1;
	
	public MailingListDAO() throws DAOException {
		try {
			BeanTable<MailingList> table = BeanTable.getInstance(MailingList.class, "mailinglist");
			if (!table.exists())
				table.create("mlid");
			
			table.setIdleConnectionCleanup(true);
			factory = table.getFactory();
			
			if (factory.getBeanCount() > 0)
				mlid = factory.match(MatchArg.max("mlid"))[0].getMlid() + 1;
			
		} catch (BeanFactoryException e) {
			throw new DAOException(e);
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public void create(MailingList ml, UserDAO userDAO) throws DAOException {
		try {
			// Check for foreign key constraint
			if (userDAO.lookup(ml.getUserid()) == null) {
				throw new DAOException("userid must exist in user table");
			}
			
			Transaction.begin();
			MailingList dbml = factory.create(ml.getMlid());
			factory.copyInto(ml, dbml);
			mlid++;
			Transaction.commit();
		} catch (DuplicateKeyException e) {
			throw new DAOException("A mailinglist with mlid " + ml.getMlid() + " already exists");
		} catch (RollbackException e) {
			throw new DAOException(e);
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}

	public MailingList lookup(int mlid) throws DAOException {
		try {
			return factory.lookup(mlid);
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	// Returns a unique mailing list by userid,name tuple. Based on invariant that they are unique.
	public MailingList getMailingListByUseridName(String userid, String name) throws DAOException {
		try {
			MailingList[] ml = factory.match(MatchArg.equals("userid", userid), MatchArg.equals("name", name));
			if (ml.length != 1)
				throw new DAOException("Invariant error");
			return ml[0];
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public MailingList[] getMailingListByUserid(String userid) throws DAOException {
		try {
			return factory.match(MatchArg.equals("userid", userid));
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public MailingList[] getMailingListByName(String name) throws DAOException {
		try {
			return factory.match(MatchArg.equals("name", name));
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public void delete(int mlid) throws DAOException {
		try {
			Transaction.begin();
			MailingList dbml = lookup(mlid);
			if (dbml == null)
				throw new DAOException("MailingList with mlid " + mlid + " doesn't exist");
			factory.delete(mlid);
			Transaction.commit();
		} catch (RollbackException e) {
			throw new DAOException(e);
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}

	public int size() throws DAOException {
		try {
			return factory.getBeanCount();
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public int getMlid() {
		return mlid;
	}
}
